package com.eflyme.learn.nc;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ucar.ma2.*;
import ucar.nc2.Attribute;
import ucar.nc2.Dimension;
import ucar.nc2.Variable;
import ucar.nc2.write.NetcdfFormatWriter;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * @author LiShixi 2021/2/3 3:12 下午
 * @email loyy77@163.com
 */
public class NcWrite {
    private Logger logger = LoggerFactory.getLogger(NcWrite.class);

    public void write(String ncFile) {
        // 1) Create a new netCDF-3 file builder with the given path and file name
        NetcdfFormatWriter.Builder builder = NetcdfFormatWriter.createNewNetcdf3(ncFile);
        // 默认填充0
        builder.setFill(true);
        // 2) Create two Dimensions, named lat and lon, of lengths 64 and 129 respectively, and add them to the root group
        Dimension latDim = builder.addDimension("lat", 64);
        Dimension lonDim = builder.addDimension("lon", 128);

        List<Dimension> dims = new ArrayList<>();
        dims.add(latDim);
        dims.add(lonDim);

        // 3) Create a builder for a Variable named temperature, or type double, with shape (lat, lon), and add to the root
        // group
        Variable.Builder t = builder.addVariable("TEM", DataType.DOUBLE, dims);

        // 4) Add a string Attribute to the temperature Variable, with name units and value K
        t.addAttribute(new Attribute("units", "°C"));

        // 5) Create a 1D integer Array Attribute using Attribute.Builder,with name scale and value (1,2,3)
        // and add to the temperature Variables
        Array data = Array.factory(DataType.INT, new int[] {3}, new int[] {1, 2, 3});
        t.addAttribute(Attribute.builder("scale").setValues(data).build());

        // 6) Create a Variable named svar or type character with length 80
        Dimension svar_len = builder.addDimension("svar_len", 80);
        builder.addVariable("svar", DataType.CHAR, "svar_len");

        // 7) Create a 2D Variable names names of type character with length 80
        Dimension names = builder.addDimension("names", 3);
        builder.addVariable("names", DataType.CHAR, "names svar_len");

        // 8) Create a scalar Variable names scalar or type double.
        // Note that the empty ArrayList means that it is a scalar, i.e. has no dimensions
        builder.addVariable("scalar", DataType.DOUBLE, new ArrayList<Dimension>());

        // 9) Create various global Attributes of different types
        builder.addAttribute(new Attribute("versionStr", "v"));
        builder.addAttribute(new Attribute("versionD", 1.2));
        builder.addAttribute(new Attribute("versionF", (float) 1.2));
        builder.addAttribute(new Attribute("versionI", 1));
        builder.addAttribute(new Attribute("versionS", (short) 2));
        builder.addAttribute(new Attribute("versionB", (byte) 3));

        // 10) Now that the metadata (Dimensions, Variables, and Attributes) is added to the builder, build the writer
        // At this point, the (empty) file will be written to disk, and the metadata is fixed and cannot be changed or
        // added.
        try (NetcdfFormatWriter writer = builder.build()) {

            // write data
            // 1) Create a 2D Array of the same shape as temperature(lat, lon) and fill it with some values
            Variable v = writer.findVariable("TEM");
            int[] shape = v.getShape();
            ArrayDouble A = new ArrayDouble.D2(shape[0], shape[1]);
            Index ima = A.getIndex();
            for (int i = 0; i < shape[0]; i++) {
                for (int j = 0; j < shape[1]; j++) {
                    A.setDouble(ima.set(i, j), 0.5*(i));
                }
            }

            // 2) Write the data to the temperature Variable, with origin all zeros.
            // Shape is taken from the data Array.

            // initialized to zeros
            // int[] origin = new int[2];
            try {
                writer.write(v,A);
            } catch (IOException | InvalidRangeException e) {
                logger.error(e.getMessage());
            }
        } catch (IOException e) {
            logger.error(e.getMessage());
        }
    }
}
